#ifndef CHRONO_FUNCTIONS_H_
#define CHRONO_FUNCTIONS_H_

#include <stdint.h>

typedef struct opp_chrono {
	struct timespec timer_s, timer_e;
	struct timespec nonterm_timer_s, nonterm_timer_e;
	struct timespec prec_timer_s, prec_timer_e;
	struct timespec stacking_timer_s, stacking_timer_e;
	struct timespec reduction_timer_s, reduction_timer_e;
	struct timespec backtrack_timer_s, backtrack_timer_e;
	struct timespec semantics_timer_s, semantics_timer_e;
	struct timespec token_timer_s, token_timer_e;
	struct timespec badtrack_timer_s, badtrack_timer_e;
	struct timespec term_timer_s, term_timer_e;
	int64_t nonterm_timer_t, prec_timer_t, stacking_timer_t,
	    reduction_timer_t, backtrack_timer_t, semantics_timer_t,
	    token_timer_t, badtrack_timer_t, term_timer_t, timer_t;
} opp_chrono;


#ifdef CHRONO
#define CHRONO_GETTIME(timer) clock_gettime(CLOCK_REALTIME, (timer));
#else
#define CHRONO_GETTIME(timer)
#endif

#ifdef CHRONO
#define CHRONO_TIMER(timer_s, timer_e, timer_t) {\
    struct timespec chrono_timer_dif; \
    clock_gettime(CLOCK_REALTIME, (timer_e)); \
    chrono_timer_dif.tv_sec = (timer_e)->tv_sec - (timer_s)->tv_sec; \
    chrono_timer_dif.tv_nsec = (timer_e)->tv_nsec - (timer_s)->tv_nsec; \
    *(timer_t) += chrono_timer_dif.tv_sec*1000000000 + chrono_timer_dif.tv_nsec; \
}
#else
#define CHRONO_TIMER(timer_s, timer_e, timer_t)
#endif

#ifdef CHRONO
#define CHRONO_METER(chrono) {\
    CHRONO_TIMER(&(chrono)->timer_s, &(chrono)->timer_e, &(chrono)->timer_t) \
    fprintf(stderr, "Timers:\n\tnonterm: %ld,\n\tprec: %ld,\n\tstacking: %ld,\n\treducing: %ld of which: \
        \n\t\tbacktrack: %ld,\n\t\tsemantics: %ld,\n\t\ttoken: %ld,\n\t\tbadtrack: %ld,\n\t\tterm: %ld\n\tTotal time: %ld\n", \
         (chrono)->nonterm_timer_t, (chrono)->prec_timer_t, (chrono)->stacking_timer_t, (chrono)->reduction_timer_t, (chrono)->backtrack_timer_t, \
         (chrono)->semantics_timer_t, (chrono)->token_timer_t, (chrono)->badtrack_timer_t, (chrono)->term_timer_t, (chrono)->timer_t); \
}
#else
#define CHRONO_METER(chrono)
#endif

#endif
